#pragma once
#include <stdint.h>
#include <stdbool.h>

#define MAX_SCB_USER_DI_NUM 16
#define MAX_SCB_USER_DO_NUM 16
#define MAX_PSCB_USER_DO_NUM 8
#define MAX_SCB_SAFETY_CHANNEL 8

// 通过SDO 查询的信息
typedef struct SCBCabStatus
{
    double cabTemperature;
    double robotAveragePower;
    double robotAverageCurrent;
    double robotVoltage;
    int scbMajorVersion;
    int scbMinorVersion;
    unsigned int cabinetID;
    unsigned int currRunTime;
    unsigned int accuRunTime;
} SCBCabStatus;

// CAN : 0x192 报文反馈， byte0-byte1
typedef struct SCBUserDI
{
    bool b[MAX_SCB_USER_DI_NUM];
} SCBUserDI;

// CAN : 0x192 报文反馈， byte2-byte3
typedef struct SCBLocalDIType
{
    uint8_t local_run_state : 1;    //0:application 1:boot
    uint8_t local_pwr_off_req : 1;  // 1:未检测到，0:检测到
    uint8_t local_usr_stop_2 : 1;   // 1:未检测到，0:检测到
    uint8_t local_usr_stop_1 : 1;   // 1:未检测到，0:检测到
    uint8_t local_usr_estop_2 : 1;  // 1:未检测到，0:检测到
    uint8_t local_usr_estop_1 : 1;  // 1:未检测到，0:检测到
    uint8_t local_bp_estop_2 : 1;   // 1:未检测到，0:检测到
    uint8_t local_bp_estop_1 : 1;   // 1:未检测到，0:检测到

    uint8_t local_di_9 : 1;
    uint8_t local_reset_button : 1;  //1：被按下，不会触发安全信号 0：未被按下，会触发安全信号
    uint8_t local_mode_sel : 1;
    uint8_t local_three_position_enabling : 1;  // 1: OFF, 0 : ON
    uint8_t local_sfgrd_rst : 1;
    uint8_t local_reduce : 1;
    uint8_t local_add_sfgrd_stop : 1;
    uint8_t local_add_estop : 1;

} SCBLocalDIType;

// CAN: 0x292报文反馈
typedef struct SCBAISignal
{
    uint8_t ai_type;
    uint16_t ai_data_1;
    uint16_t ai_data_2;
    uint8_t uhi_pules_direction;
    uint16_t uhi_pules;
} SCBAISignal;

typedef struct PSCBAISignal
{
    uint8_t dio_type;
    uint8_t stuck_voltage;
    uint8_t rgb_status;  // 实际未使用
    uint8_t resv_4;
    uint8_t resv_5;
    uint8_t resv_6;
    uint8_t resv_7;
    uint8_t resv_8;
} PSCBAISignal;

typedef union AISignalUnion
{
    SCBAISignal scb_ai_signal;
    PSCBAISignal pscb_ai_signal;
} AISignalUnion;

typedef struct SCBDO
{
    bool user_do[16];
    bool local_do[16];

    // #TODO 下面这些未解析
    uint8_t io_type_bit0 : 1;
    uint8_t io_type_bit1 : 1;
    uint8_t io_type_bit2 : 1;
    uint8_t io_type_bit3 : 1;
    uint8_t ao_data_1_h : 4;
    uint8_t ao_data_1_l;
    uint8_t ao_data_2_h;
    uint8_t ao_data_2_l;

} SCBDO;

typedef struct PSCBDO
{
    bool user_do[8];
    uint8_t user_resv;
    uint8_t user_resv_1;
    uint8_t user_resv_2;
    uint8_t user_resv_3;
    uint8_t user_resv_4;
    uint8_t user_resv_5;
    uint8_t user_resv_6;
} PSCBDO;

typedef struct PSCBUserDO
{
    bool val[8];
} PSCBUserDO;
typedef union DOSignalUnion
{
    SCBDO scb_do_ao_feedback;
    PSCBDO pscb_do_feedback;
} DOSignalUnion;

// #TODO, scb 与 PSB的这个结构体存在差异
typedef struct LocalDOCmd
{
    uint8_t local_do_8 : 1;               // reserve
    uint8_t local_do_pwr_bp : 1;          // 手柄电源控制
    uint8_t local_do_req_reflash_bp : 1;  //控制器请求刷新手柄固件
    uint8_t local_do_5 : 1;               // 控制器完成刷新安全板
    uint8_t local_re_flash : 1;           //控制器请求刷新安全板
    uint8_t local_dis_robot_can : 1;      //控制器请求刷新伺服驱动
    uint8_t local_pwr_ipc : 1;            // 请求关机
    uint8_t local_pwr_robot : 1;          //机器人本体电源控制
    uint8_t local_do_9 : 1;
    uint8_t local_do_10 : 1;
    uint8_t local_do_11 : 1;
    uint8_t local_do_12 : 1;
    uint8_t local_do_13 : 1;
    uint8_t local_do_14 : 1;
    uint8_t local_do_15 : 1;
    uint8_t local_do_16 : 1;
} LocalDOCmd;

typedef struct UserDOCmd
{
    bool val[MAX_SCB_USER_DO_NUM];
} UserDOCmd;

typedef struct SCBDOCmd
{
    UserDOCmd user_do;
    LocalDOCmd local_do;
    uint8_t resv_1;
    uint8_t resv_2;
    uint8_t resv_3;
    uint8_t resv_4;
} SCBDOCmd;

typedef struct PSCBDOCmd
{
    UserDOCmd user_do;
    LocalDOCmd local_do;
    uint8_t user_do_resv_1;
    uint8_t resv_2;
    uint8_t resv_3;
    uint8_t resv_4;
} PSCBDOCmd;

typedef union DOcmdUnion
{
    SCBDOCmd do_cmd;
    PSCBDOCmd pscb_do_cmd;
} DOcmdUnion;

typedef struct UserDOType
{
    bool b[16];
} UserDOType;

typedef struct SCBAOCmd
{
    uint8_t ao_type;
    uint8_t ao_data_1_h;
    uint8_t ao_data_1_l;
    uint8_t ao_data_2_h;
    uint8_t ao_data_2_l;

    uint8_t resv_2;
    uint8_t resv_3;
    uint8_t resv_4;
} SCBAOCmd;

typedef struct PSCBAOCmd
{
    uint8_t user_dio_cfg;
    uint8_t stuck_voltage_cfg;
    uint8_t front_pnal_rgb_ctl;
    uint8_t resv_4;
    uint8_t resv_5;
    uint8_t resv_6;
    uint8_t resv_7;
    uint8_t resv_8;
} PSCBAOCmd;

typedef union AOCmdUnion
{
    SCBAOCmd scb_ao_cmd;
    PSCBAOCmd pscb_ao_cmd;
} AOCmdUnion;

typedef struct SCBSafetyDI
{
    //safety DI (reserved)
    bool safety_di_collision[8];  // 分别为0,1,2,3,4,5,7等级设置
    //reserved
    uint8_t reserved_1;
    /*safety DO feedback from SCB*/
    bool feedback_sfdo_channel[MAX_SCB_SAFETY_CHANNEL];
    uint8_t reserved_3;
    uint8_t reserved_4;
    uint8_t reserved_5;
    uint8_t reserved_6;
    uint8_t reserved_7;
} SCBSafetyDI;

typedef struct SafetyDOChannel
{
    bool val[MAX_SCB_SAFETY_CHANNEL];
} SafetyDOChannel;

typedef struct SafetyDOCmd
{
    SafetyDOChannel safety_do_channel;
    uint8_t resv_1;
    uint8_t resv_2;
    uint8_t resv_3;
    uint8_t resv_4;
    uint8_t resv_5;
    uint8_t resv_6;
    uint8_t resv_7;
} SafetyDOCmd;
typedef enum SafetyBoardType
{
    SAFETY_BOARD_UNKNOWN = 0,
    SAFETY_BOARD_SCB = 2,
    SAFETY_BOARD_PSCB = 3,
} SafetyBoardType;